import pygame
import random
import sys

# 初始化Pygame
pygame.init()

# 设置中文字体
pygame.font.init()
try:
    font = pygame.font.SysFont(['SimHei', 'Microsoft YaHei', 'Arial'], 36)
    small_font = pygame.font.SysFont(['SimHei', 'Microsoft YaHei', 'Arial'], 24)
except:
    font = pygame.font.SysFont('Arial', 36)
    small_font = pygame.font.SysFont('Arial', 24)

# 游戏常量
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
GRID_SIZE = 30
GRID_WIDTH = 10
GRID_HEIGHT = 20

# 颜色定义
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
CYAN = (0, 255, 255)
MAGENTA = (255, 0, 255)
YELLOW = (255, 255, 0)
ORANGE = (255, 165, 0)
GRAY = (128, 128, 128)

# 方块形状定义
SHAPES = [
    [[1, 1, 1, 1]],  # I
    [[1, 1], [1, 1]],  # O
    [[0, 1, 0], [1, 1, 1]],  # T
    [[1, 0, 0], [1, 1, 1]],  # J
    [[0, 0, 1], [1, 1, 1]],  # L
    [[0, 1, 1], [1, 1, 0]],  # S
    [[1, 1, 0], [0, 1, 1]]   # Z
]

# 方块颜色
SHAPE_COLORS = [CYAN, YELLOW, MAGENTA, BLUE, ORANGE, GREEN, RED]

# 创建屏幕
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("俄罗斯方块")

clock = pygame.time.Clock()

class Tetris:
    def __init__(self):
        self.reset()
        
    def reset(self):
        self.board = [[0 for _ in range(GRID_WIDTH)] for _ in range(GRID_HEIGHT)]
        self.current_piece = self.new_piece()
        self.next_piece = self.new_piece()
        self.game_over = False
        self.paused = False
        self.score = 0
        self.level = 1
        self.lines = 0
        self.fall_speed = 0.5  # 初始下落速度（秒/格）
        self.last_fall_time = pygame.time.get_ticks()
    
    def new_piece(self):
        shape_idx = random.randint(0, len(SHAPES) - 1)
        shape = SHAPES[shape_idx]
        color = SHAPE_COLORS[shape_idx]
        x = GRID_WIDTH // 2 - len(shape[0]) // 2
        y = 0
        return {"shape": shape, "color": color, "x": x, "y": y}
    
    def valid_position(self, piece, x=None, y=None, shape=None):
        if x is None:
            x = piece["x"]
        if y is None:
            y = piece["y"]
        if shape is None:
            shape = piece["shape"]
        
        for i in range(len(shape)):
            for j in range(len(shape[i])):
                if shape[i][j] == 1:
                    pos_x = x + j
                    pos_y = y + i
                    # 检查边界
                    if pos_x < 0 or pos_x >= GRID_WIDTH or pos_y >= GRID_HEIGHT:
                        return False
                    # 检查是否与已有方块重叠（忽略顶部边界外的部分）
                    if pos_y >= 0 and self.board[pos_y][pos_x] != 0:
                        return False
        return True
    
    def merge_piece(self):
        shape = self.current_piece["shape"]
        color = self.current_piece["color"]
        x = self.current_piece["x"]
        y = self.current_piece["y"]
        
        for i in range(len(shape)):
            for j in range(len(shape[i])):
                if shape[i][j] == 1:
                    pos_y = y + i
                    pos_x = x + j
                    if pos_y >= 0:
                        self.board[pos_y][pos_x] = color
    
    def clear_lines(self):
        lines_cleared = 0
        i = GRID_HEIGHT - 1
        while i >= 0:
            if all(cell != 0 for cell in self.board[i]):
                # 清除当前行
                del self.board[i]
                # 在顶部添加新行
                self.board.insert(0, [0 for _ in range(GRID_WIDTH)])
                lines_cleared += 1
            else:
                i -= 1
        
        # 根据消除行数加分
        if lines_cleared == 1:
            self.score += 100 * self.level
        elif lines_cleared == 2:
            self.score += 300 * self.level
        elif lines_cleared == 3:
            self.score += 500 * self.level
        elif lines_cleared == 4:
            self.score += 800 * self.level
        
        self.lines += lines_cleared
        
        # 根据消除行数调整等级和速度
        new_level = self.lines // 10 + 1
        if new_level > self.level:
            self.level = new_level
            self.fall_speed = max(0.05, 0.5 - (self.level - 1) * 0.05)
    
    def rotate_piece(self):
        shape = self.current_piece["shape"]
        # 旋转矩阵
        rotated_shape = [[shape[j][i] for j in range(len(shape) - 1, -1, -1)] for i in range(len(shape[0]))]
        
        if self.valid_position(self.current_piece, shape=rotated_shape):
            self.current_piece["shape"] = rotated_shape
    
    def move(self, dx, dy):
        if self.valid_position(self.current_piece, x=self.current_piece["x"] + dx, y=self.current_piece["y"] + dy):
            self.current_piece["x"] += dx
            self.current_piece["y"] += dy
            return True
        return False
    
    def drop_down(self):
        if not self.move(0, 1):
            self.merge_piece()
            self.clear_lines()
            self.current_piece = self.next_piece
            self.next_piece = self.new_piece()
            # 检查游戏是否结束
            if not self.valid_position(self.current_piece):
                self.game_over = True
    
    def hard_drop(self):
        while self.move(0, 1):
            pass
        self.drop_down()
        # 硬降加分
        self.score += 2 * self.level
    
    def update(self):
        if self.paused or self.game_over:
            return
        
        current_time = pygame.time.get_ticks()
        if current_time - self.last_fall_time > self.fall_speed * 1000:
            self.drop_down()
            self.last_fall_time = current_time
    
    def draw(self):
        screen.fill(BLACK)
        
        # 绘制游戏区域边框
        game_area_x = (SCREEN_WIDTH - GRID_WIDTH * GRID_SIZE) // 2 - 100
        pygame.draw.rect(screen, WHITE, (game_area_x - 2, 50 - 2, GRID_WIDTH * GRID_SIZE + 4, GRID_HEIGHT * GRID_SIZE + 4), 2)
        
        # 绘制游戏板
        for y in range(GRID_HEIGHT):
            for x in range(GRID_WIDTH):
                if self.board[y][x] != 0:
                    color = self.board[y][x]
                    pygame.draw.rect(screen, color, 
                                    (game_area_x + x * GRID_SIZE, 50 + y * GRID_SIZE, GRID_SIZE - 1, GRID_SIZE - 1))
        
        # 绘制当前方块
        if not self.game_over:
            shape = self.current_piece["shape"]
            color = self.current_piece["color"]
            piece_x = self.current_piece["x"]
            piece_y = self.current_piece["y"]
            
            for i in range(len(shape)):
                for j in range(len(shape[i])):
                    if shape[i][j] == 1:
                        pos_x = game_area_x + (piece_x + j) * GRID_SIZE
                        pos_y = 50 + (piece_y + i) * GRID_SIZE
                        if pos_y >= 50:  # 只绘制在可见区域内的部分
                            pygame.draw.rect(screen, color, 
                                            (pos_x, pos_y, GRID_SIZE - 1, GRID_SIZE - 1))
        
        # 绘制下一个方块预览
        next_area_x = game_area_x + GRID_WIDTH * GRID_SIZE + 50
        pygame.draw.rect(screen, WHITE, (next_area_x - 2, 50 - 2, 150 + 4, 150 + 4), 2)
        next_text = font.render("下一个", True, WHITE)
        screen.blit(next_text, (next_area_x + 30, 10))
        
        next_shape = self.next_piece["shape"]
        next_color = self.next_piece["color"]
        next_shape_height = len(next_shape)
        next_shape_width = len(next_shape[0])
        
        # 居中显示下一个方块
        start_x = next_area_x + 75 - (next_shape_width * GRID_SIZE) // 2
        start_y = 50 + 75 - (next_shape_height * GRID_SIZE) // 2
        
        for i in range(next_shape_height):
            for j in range(next_shape_width):
                if next_shape[i][j] == 1:
                    pygame.draw.rect(screen, next_color, 
                                    (start_x + j * GRID_SIZE, start_y + i * GRID_SIZE, GRID_SIZE - 1, GRID_SIZE - 1))
        
        # 绘制分数、等级和消除行数
        score_text = font.render("分数: {0}".format(self.score), True, WHITE)
        level_text = font.render("等级: {0}".format(self.level), True, WHITE)
        lines_text = font.render("行数: {0}".format(self.lines), True, WHITE)
        
        screen.blit(score_text, (next_area_x + 10, 220))
        screen.blit(level_text, (next_area_x + 10, 270))
        screen.blit(lines_text, (next_area_x + 10, 320))
        
        # 绘制操作说明
        controls_text = small_font.render("操作说明:", True, WHITE)
        key1_text = small_font.render("← →: 左右移动", True, WHITE)
        key2_text = small_font.render("↑: 旋转", True, WHITE)
        key3_text = small_font.render("↓: 加速下落", True, WHITE)
        key4_text = small_font.render("空格: 直接下落", True, WHITE)
        key5_text = small_font.render("P: 暂停/继续", True, WHITE)
        key6_text = small_font.render("R: 重新开始", True, WHITE)
        
        screen.blit(controls_text, (next_area_x - 10, 370))
        screen.blit(key1_text, (next_area_x - 10, 400))
        screen.blit(key2_text, (next_area_x - 10, 430))
        screen.blit(key3_text, (next_area_x - 10, 460))
        screen.blit(key4_text, (next_area_x - 10, 490))
        screen.blit(key5_text, (next_area_x - 10, 520))
        screen.blit(key6_text, (next_area_x - 10, 550))
        
        # 绘制暂停信息
        if self.paused:
            pause_surf = pygame.Surface((SCREEN_WIDTH, SCREEN_HEIGHT), pygame.SRCALPHA)
            pause_surf.fill((0, 0, 0, 128))
            screen.blit(pause_surf, (0, 0))
            pause_text = font.render("游戏暂停", True, WHITE)
            screen.blit(pause_text, (SCREEN_WIDTH // 2 - pause_text.get_width() // 2, 
                                    SCREEN_HEIGHT // 2 - pause_text.get_height() // 2))
        
        # 绘制游戏结束信息
        if self.game_over:
            game_over_surf = pygame.Surface((SCREEN_WIDTH, SCREEN_HEIGHT), pygame.SRCALPHA)
            game_over_surf.fill((0, 0, 0, 192))
            screen.blit(game_over_surf, (0, 0))
            game_over_text = font.render("游戏结束", True, RED)
            final_score_text = font.render("最终分数: {0}".format(self.score), True, WHITE)
            final_lines_text = font.render("消除行数: {0}".format(self.lines), True, WHITE)
            restart_text = small_font.render("按 R 键重新开始", True, WHITE)
            
            screen.blit(game_over_text, (SCREEN_WIDTH // 2 - game_over_text.get_width() // 2, 
                                        SCREEN_HEIGHT // 2 - 100))
            screen.blit(final_score_text, (SCREEN_WIDTH // 2 - final_score_text.get_width() // 2, 
                                          SCREEN_HEIGHT // 2 - 50))
            screen.blit(final_lines_text, (SCREEN_WIDTH // 2 - final_lines_text.get_width() // 2, 
                                          SCREEN_HEIGHT // 2))
            screen.blit(restart_text, (SCREEN_WIDTH // 2 - restart_text.get_width() // 2, 
                                      SCREEN_HEIGHT // 2 + 50))
        
        pygame.display.flip()

def main():
    tetris = Tetris()
    
    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            elif event.type == pygame.KEYDOWN:
                if tetris.game_over:
                    if event.key == pygame.K_r:
                        tetris.reset()
                else:
                    if event.key == pygame.K_p:
                        tetris.paused = not tetris.paused
                    elif event.key == pygame.K_r:
                        tetris.reset()
                    elif not tetris.paused:
                        if event.key == pygame.K_LEFT:
                            tetris.move(-1, 0)
                        elif event.key == pygame.K_RIGHT:
                            tetris.move(1, 0)
                        elif event.key == pygame.K_DOWN:
                            tetris.move(0, 1)
                            # 软降加分在update方法中处理更合适，这里暂时注释掉
                        elif event.key == pygame.K_UP:
                            tetris.rotate_piece()
                        elif event.key == pygame.K_SPACE:
                            tetris.hard_drop()
        
        tetris.update()
        tetris.draw()
        clock.tick(60)

if __name__ == "__main__":
    main()